# complete.py (增强版)
"""Tab 补全功能模块，包含所有命令的自动补全逻辑"""

import os
import glob
import readline
from pathlib import Path
from common import ( # type: ignore
    COMMAND_LIST, COMMAND_OPTIONS, SORT_OPTIONS,
    COMPLETION_CONFIG
)

class Completer:
    """Tab 补全器，负责处理所有命令的自动补全"""
    
    def __init__(self, sftp_instance):
        """
        初始化补全器
        
        参数:
            sftp_instance: BaiduPanSFTP 实例，用于访问状态信息
        """
        self.sftp = sftp_instance
        self.completion_matches = []
        self.remote_file_cache = {}
        self.local_file_cache = {}
        
    def complete(self, text, state):
        """
        Tab 补全主函数，与 readline 兼容
        
        参数:
            text: 当前输入的文本
            state: 补全状态
            
        返回:
            匹配的补全项或 None
        """
        if state == 0:
            self._update_completion_matches(text)
        
        try:
            return self.completion_matches[state]
        except IndexError:
            return None
    
    def _update_completion_matches(self, text):
        """更新补全匹配项"""
        line = readline.get_line_buffer()
        begin = readline.get_begidx()
        end = readline.get_endidx()
        
        tokens = line.split()
        
        if not tokens:
            # 空行，补全命令
            self._complete_command(text)
        else:
            if begin == 0:
                # 命令补全
                self._complete_command(text)
            else:
                # 参数补全
                cmd = tokens[0]
                self._complete_argument(cmd, text, line, tokens, begin)
    
    def _complete_command(self, text):
        """补全命令"""
        if COMPLETION_CONFIG['completion_ignore_case']:
            text = text.lower()
            matches = [cmd for cmd in COMMAND_LIST if cmd.lower().startswith(text)]
        else:
            matches = [cmd for cmd in COMMAND_LIST if cmd.startswith(text)]
        
        # 限制补全项数量
        self.completion_matches = matches[:COMPLETION_CONFIG['max_completion_items']]
    
    def _complete_argument(self, cmd, text, line, tokens, begin):
        """根据命令补全参数"""
        # 使用命令映射表来确定补全方法
        completion_methods = {
            'ls': self._complete_ls,
            'lls': self._complete_lls,
            'cd': self._complete_remote_path,
            'get': self._complete_remote_path,
            'put': self._complete_local_path,
            'rm': self._complete_remote_path,
            'mv': self._complete_remote_path,
            'cp': self._complete_remote_path,
            'tree': self._complete_remote_path,
            'meta': self._complete_remote_path,
            'rename': self._complete_remote_path,
            'lcd': self._complete_local_path,
            'lls': self._complete_local_path,
            'lmkdir': self._complete_local_path,
            'config': self._complete_config,
            'debug': self._complete_debug,
            'help': self._complete_help,
        }
        
        # 调用相应的补全方法
        method = completion_methods.get(cmd, self._complete_default)
        method(text, line, tokens, begin)
    
    def _complete_default(self, text, line, tokens, begin):
        """默认补全方法"""
        self.completion_matches = []
    
    def _complete_remote_path(self, text, line, tokens, begin):
        """补全远程路径"""
        try:
            current_dir = self.sftp.remote_cwd
            
            if '/' in text:
                dir_part = os.path.dirname(text)
                file_part = os.path.basename(text)
                
                if dir_part == '':
                    dir_part = '/'
                elif not dir_part.startswith('/'):
                    dir_part = os.path.join(current_dir, dir_part).replace('\\', '/')
            else:
                dir_part = current_dir
                file_part = text
            
            if not dir_part.startswith('/'):
                dir_part = '/' + dir_part
            
            # 检查缓存
            if dir_part in self.remote_file_cache:
                items = self.remote_file_cache[dir_part]
            else:
                # 获取远程目录内容
                result = self.sftp.commands.list_files(dir_part)
                if 'list' in result:
                    items = result['list']
                    self.remote_file_cache[dir_part] = items
                else:
                    items = []
            
            matches = []
            for item in items:
                name = item['server_filename']
                if name.startswith(file_part):
                    if item['isdir'] == 1:
                        matches.append(name + '/')
                    else:
                        matches.append(name)
            
            # 如果只有一个匹配项且是目录，自动添加斜杠
            if len(matches) == 1 and matches[0].endswith('/'):
                readline.insert_text('/')
            
            self.completion_matches = matches
            
        except Exception:
            self.completion_matches = []
    
    def _complete_local_path(self, text, line, tokens, begin):
        """补全本地路径"""
        if text == "":
            text = "./"
        
        matches = []
        expanded = os.path.expanduser(text)
        
        # 处理通配符
        if '*' in expanded or '?' in expanded:
            glob_matches = glob.glob(expanded + '*')
            matches = [os.path.basename(match) + ('/' if os.path.isdir(match) else '') for match in glob_matches]
        else:
            dirname = os.path.dirname(expanded)
            basename = os.path.basename(expanded)
            
            if dirname == "":
                dirname = "."
            
            if os.path.exists(dirname) and os.path.isdir(dirname):
                for filename in os.listdir(dirname):
                    if filename.startswith(basename):
                        fullpath = os.path.join(dirname, filename)
                        if os.path.isdir(fullpath):
                            matches.append(filename + '/')
                        else:
                            matches.append(filename)
        
        self.completion_matches = matches
    
    def _complete_config(self, text, line, tokens, begin):
        """为 config 命令提供补全"""
        if len(tokens) == 1:
            # config 命令的子命令
            options = COMMAND_OPTIONS.get('config', [])
            matches = [opt for opt in options if opt.startswith(text)]
            self.completion_matches = matches
        elif len(tokens) == 2 and tokens[1] == 'set':
            # config set 的选项
            options = ['--client-id', '--client-secret', '--redirect-uri']
            matches = [opt for opt in options if opt.startswith(text)]
            self.completion_matches = matches
        else:
            self.completion_matches = []
    
    def _complete_debug(self, text, line, tokens, begin):
        """为 debug 命令提供补全"""
        options = COMMAND_OPTIONS.get('debug', [])
        matches = [opt for opt in options if opt.startswith(text)]
        self.completion_matches = matches
    
    def _complete_help(self, text, line, tokens, begin):
        """为 help 命令提供补全"""
        matches = [cmd for cmd in COMMAND_LIST if cmd.startswith(text)]
        self.completion_matches = matches
    
    def _complete_ls(self, text, line, tokens, begin):
        """为 ls 命令提供补全"""
        # 检查是否正在输入选项
        if tokens[-1].startswith('-'):
            # 补全选项
            options = COMMAND_OPTIONS.get('ls', [])
            matches = [opt for opt in options if opt.startswith(text)]
            self.completion_matches = matches
        elif len(tokens) >= 2 and tokens[-2] == '-s':
            # 补全排序选项
            options = list(SORT_OPTIONS.keys())
            matches = [opt for opt in options if opt.startswith(text)]
            self.completion_matches = matches
        else:
            # 补全远程路径
            self._complete_remote_path(text, line, tokens, begin)
    
    def _complete_lls(self, text, line, tokens, begin):
        """为 lls 命令提供补全"""
        # 检查是否正在输入选项
        if tokens[-1].startswith('-'):
            # 补全选项
            options = COMMAND_OPTIONS.get('lls', [])
            matches = [opt for opt in options if opt.startswith(text)]
            self.completion_matches = matches
        elif len(tokens) >= 2 and tokens[-2] == '-s':
            # 补全排序选项
            options = list(SORT_OPTIONS.keys())
            matches = [opt for opt in options if opt.startswith(text)]
            self.completion_matches = matches
        else:
            # 补全本地路径
            self._complete_local_path(text, line, tokens, begin)
    
    def clear_cache(self):
        """清空补全缓存"""
        self.remote_file_cache = {}
        self.local_file_cache = {}
    
    def refresh_remote_cache(self, path=None, file_list=[]):
        """刷新远程文件缓存"""
        if path is None:
            path = self.sftp.remote_cwd
        
        try:
            list = []
            if file_list and len(file_list) > 0:
                list = file_list
            else:
                result = self.sftp.commands.list_files(path)
                if 'list' in result:
                    list = result['list']

            self.remote_file_cache[path] = list
            return True
        except:
            pass
        
        return False
